home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C++ / Applications / PICSee Dust 1.01 / Quaternary Source / Marquee.c < prev    next >
Text File  |  1995-11-16  |  6KB  |  229 lines

  1. /*
  2. ** James "im" Beninghaus
  3. */
  4.  
  5. /*
  6.     Version history
  7.  
  8.         2.0    Nov 5 95 HTD
  9.             "Updated" code for today's generation ;-).
  10.             Added a callback parameter (so you could display the mouse coordinates
  11.             while dragging the marquee, for example).
  12.             Also added a "crop area" - you can confine the marquee selection
  13.             to this area.
  14.  
  15.         2.1 Nov 6
  16.             Added TrackMarqueeOpaque() and ConstrainPointWithinRect().
  17.             The problem with TrackMarquee occurs with color images that have
  18.             grayish colors. Because of the use of patXor, the resulting
  19.             marquee is grayish as well. The marquee is then VERY hard to see.
  20.             The problem is, if you invert gray, you pretty much get gray!
  21.             So TrackMarqueeOpaque adds an update callback procedure.
  22.             TrackMarqueeOpaque does not use any patXor tricks but instead
  23.             just plainly draws the marquee rect. However, we need a way to
  24.             update the marquee (to erase the old marquee rect) which is
  25.             what the callback proc is for. 
  26. */
  27.  
  28. #include "Marquee.h"
  29.  
  30. // ---------------------------------------------------------------------------
  31.  
  32. #define    TICKDELAY    2
  33.  
  34. /*
  35. ** Description
  36. **        TrackMarquee will display a marquee similar to the 
  37. **        selection rectangle tool in MacPaint™. It is assumed that the
  38. **        current port has been set before calling. 
  39. **
  40. ** Parameters
  41. **        start            : the local coordinates where the mouse down occured. Mandatory.
  42. **        trackMouseProc    : a callback procedure that will give you the current mouse's
  43. **                          location. Optional (pass NULL)
  44. **        cropToRect        : a rect in which to confine the marquee. Optional (pass NULL)
  45. **        resultRect        : the final rectangle that was selected. Mandatory
  46. */
  47.  
  48.  
  49. void TrackMarquee(
  50.     Point            start,
  51.     const Rect        *cropToRect,
  52.     Rect            *resultRect) {
  53.     /*
  54.     ** there are fifteen patterns defined here 
  55.     ** each one eight bytes long starting at :
  56.     ** patterns[0], patterns[1], patterns[2], patterns[3],
  57.     ** patterns[4], patterns[5], patterns[6], patterns[7]
  58.     */
  59.     static    unsigned char    patterns[] = {
  60.         0xF8, 0xF1, 0xE3, 0xC7, 0x8F, 
  61.         0x1F, 0x3E, 0x7C, 0xF8, 0xF1, 
  62.         0xE3, 0xC7, 0x8F, 0x1F, 0x3E
  63.     };
  64.     
  65.     Point        mouse;        /* the current mouse location */
  66.     short        index;        /* the index of the current patterns array */
  67.     Rect        nowRect,    /* the current rectangle to be framed */
  68.                 thenRect;    /* the last rectangle to be framed */
  69.     long        nowTicks,    /* the current tick count */
  70.                 thenTicks;    /* the last tick count */
  71.     PenState    penState;    /* the saved pen state on entry to procedure */
  72.  
  73.     
  74.     thenTicks = 0;
  75.     index = 0;
  76.     
  77.     GetPenState(&penState);
  78.     PenMode(patXor);
  79.  
  80.     PenPat((ConstPatternParam)&patterns[index]);
  81.     SetRect(&nowRect, start.h, start.v, start.h, start.v);
  82.     FrameRect(&nowRect);
  83.     thenRect = nowRect;
  84.     
  85.     while (StillDown()) {
  86.         nowTicks = TickCount();
  87.         GetMouse(&mouse);
  88.  
  89.         if (cropToRect != NULL) {
  90.             ConstrainPointWithinRect(&mouse, cropToRect);
  91.         }
  92.  
  93.         SetMobiusRect(&nowRect, start.h, start.v, mouse.h, mouse.v);
  94.         if (((thenTicks + TICKDELAY) < nowTicks ? thenTicks = nowTicks, true : false) || 
  95.         (!EqualRect(&nowRect, &thenRect))) {
  96.  
  97.             FrameRect(&thenRect);
  98.             index = index < 7 ? index + 1 : 0;
  99.  
  100.             PenPat((ConstPatternParam)&patterns[index]);
  101.             FrameRect(&nowRect);
  102.             thenRect = nowRect;
  103.         }
  104.     }
  105.     FrameRect(&thenRect);
  106.     
  107.     SetPenState(&penState);
  108.     *resultRect = thenRect;
  109. } // END TrackMarquee
  110.  
  111. // ---------------------------------------------------------------------------
  112.  
  113. void TrackMarqueeOpaque(
  114.     Point            start,
  115.     TrackUpdateProc trackUpdateProc,
  116.     const RGBColor    *marqueeColor,
  117.     const Rect        *cropToRect,
  118.     Rect            *resultRect) {
  119.     
  120.     Point        mouse;        /* the current mouse location */
  121.     Rect        nowRect,    /* the current rectangle to be framed */
  122.                 thenRect;    /* the last rectangle to be framed */
  123.     long        nowTicks,    /* the current tick count */
  124.                 thenTicks;    /* the last tick count */
  125.  
  126.     thenTicks = 0;
  127.     
  128.     SetRect(&nowRect, start.h, start.v, start.h, start.v);
  129.     thenRect = nowRect;
  130.     
  131.     while (StillDown()) {
  132.         nowTicks = TickCount();
  133.         GetMouse(&mouse);
  134.  
  135.         if (cropToRect != NULL) {
  136.             ConstrainPointWithinRect(&mouse, cropToRect);
  137.         }
  138.  
  139.         SetMobiusRect(&nowRect, start.h, start.v, mouse.h, mouse.v);
  140.  
  141.         if (nowTicks > (thenTicks + TICKDELAY)) {
  142.             thenTicks = nowTicks;
  143.             // Erase old marquee
  144.             trackUpdateProc(&thenRect, &nowRect);
  145.             FrameMarquee(&nowRect, marqueeColor);
  146.             thenRect = nowRect;
  147.         }
  148.         else if (!EqualRect(&nowRect, &thenRect) && nowTicks > (thenTicks + TICKDELAY)) {
  149.             thenTicks = nowTicks;
  150.             trackUpdateProc(&thenRect, &nowRect);
  151.             FrameMarquee(&nowRect, marqueeColor);
  152.             thenRect = nowRect;
  153.         }
  154.     }
  155.     // Erase any visages of the marquee
  156.     trackUpdateProc(&thenRect, &nowRect);
  157.     
  158.     *resultRect = thenRect;
  159. } // END TrackMarqueeOpaque
  160.  
  161. // ---------------------------------------------------------------------------
  162.  
  163. static long sIndex = 0;        /* the index of the current patterns array */
  164.  
  165. void FrameMarquee(const Rect *marqueeRect, const RGBColor *marqueeColor) {
  166.     static    unsigned char    patterns[] = {
  167.         0xF8, 0xF1, 0xE3, 0xC7, 0x8F, 
  168.         0x1F, 0x3E, 0x7C, 0xF8, 0xF1, 
  169.         0xE3, 0xC7, 0x8F, 0x1F, 0x3E
  170.     };
  171.     
  172.     PenState penState;
  173.     RGBColor saveFore, saveBack, backColor;
  174.  
  175.     GetPenState(&penState);
  176.     GetForeColor(&saveFore);
  177.     GetBackColor(&saveBack);
  178.     backColor.red = backColor.green = backColor.blue = 0xFFFF; // White
  179.     RGBBackColor(&backColor);
  180.  
  181.     sIndex = sIndex < 7 ? sIndex + 1 : 0;
  182.     PenPat((ConstPatternParam)&patterns[sIndex]);
  183.     if (marqueeColor != NULL)
  184.         RGBForeColor(marqueeColor);
  185.     FrameRect(marqueeRect);
  186.  
  187.     RGBForeColor(&saveFore);
  188.     RGBBackColor(&saveBack);
  189.  
  190.     SetPenState(&penState);
  191. } // END FrameMarquee
  192.  
  193. // ---------------------------------------------------------------------------
  194.  
  195. void SetMobiusRect(
  196.     Rect    *rect,
  197.     short    anchorLeft,
  198.     short    anchorTop,
  199.     short    curRight,
  200.     short    curBottom) {
  201.  
  202.     if (anchorLeft > curRight) {
  203.         rect->left = curRight;
  204.         rect->right = anchorLeft;
  205.     } else {
  206.         rect->left = anchorLeft;
  207.         rect->right = curRight;
  208.     }
  209.     if (anchorTop > curBottom) {
  210.         rect->top = curBottom;
  211.         rect->bottom = anchorTop;
  212.     } else {
  213.         rect->top = anchorTop;
  214.         rect->bottom = curBottom;
  215.     }
  216. } // END SetMobiusRect
  217.  
  218. // ---------------------------------------------------------------------------
  219.  
  220. void ConstrainPointWithinRect(Point *point, const Rect *constrainRect) {
  221.     if (point->h < constrainRect->left)
  222.         point->h = constrainRect->left;
  223.     else if (point->h > constrainRect->right)
  224.         point->h = constrainRect->right;
  225.     if (point->v < constrainRect->top)
  226.         point->v = constrainRect->top;
  227.     else if (point->v > constrainRect->bottom)
  228.         point->v = constrainRect->bottom;
  229. } // END ConstrainPointWithinRect